﻿/*!
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

using System;
using System.Collections.Generic;

namespace Pittypat
{
    /// <summary>
    /// 对可枚举的集合进行扩展。
    /// </summary>
    public static class Enumerable
    {
        /// <summary>
        /// 检索指定的集合，查询符合指定条件的元素，并返回一个 List 集合。
        /// </summary>
        /// <typeparam name="T">集合中元素的类型。</typeparam>
        /// <param name="c">目标集合。</param>
        /// <param name="where">查询条件。</param>
        /// <returns>一个 List 集合，包含了所有符合条件的元素。如果 c 为 null，则返回一个空集合。如果 where 为 null，则返回包含所有元素的集合。</returns>
        public static List<T> Search<T>(this IEnumerable<T> c, Func<T, bool> where)
        {
            if (c == null)
            {
                // 返回一个空的集合
                return new List<T>();
            }

            if (where == null)
            {
                // 没有提供查询条件时，返回整个集合
                return new List<T>(c);
            }

            // 按查询条件过滤
            var list = new List<T>(16);

            foreach (var item in c)
            {
                if (where(item))
                {
                    list.Add(item);
                }
            }

            return list;
        }

        /// <summary>
        /// 查找指定集合中第一个满足条件的元素。
        /// </summary>
        /// <typeparam name="T">集合元素的类型。</typeparam>
        /// <param name="c">目标集合。</param>
        /// <param name="where">查找条件。</param>
        /// <param name="defaultValue">当集合中不存在满足条件的元素时应该返回的默认值。</param>
        /// <returns>满足指定条件的元素或者默认值。如果 c 为 null或为空集合，或者没有满足条件的元素，返回 defaultValue。如果 where 为 null，则返回第一个元素。</returns>
        public static T Find<T>(this IEnumerable<T> c, Func<T, bool> where, T defaultValue)
        {
            if (c == null)
            {
                return defaultValue;
            }

            if (where == null)
            {
                foreach (var item in c)
                {
                    return item;
                }

                // 集合是空集合
                return defaultValue;
            }
            
            foreach (var item in c)
            {
                if (where(item))
                {
                    return item;
                }
            }

            return defaultValue;
        }

        /// <summary>
        /// 判断指定集合中是否存在指定条件的元素。
        /// </summary>
        /// <typeparam name="T">集合元素的类型。</typeparam>
        /// <param name="c">目标集合。</param>
        /// <param name="where">判断条件。</param>
        /// <returns>如果集合中存在满足指定条件的元素，则返回 true，否则返回 false。如果 c 或 where 为 null，则返回 false。</returns>
        public static bool Exists<T>(this IEnumerable<T> c, Func<T, bool> where)
        {
            if (c == null || where == null)
            {
                return false;
            }
            
            foreach (var item in c)
            {
                if (where(item))
                {
                    return true;
                }
            }

            return false;
        }
    }
}
